package main

import (
	"fmt"
	"io"
	"os"
)

type Player struct {
	name   string
	age    int
	gender string
}

func (p Player) String() string {
	return fmt.Sprintf("%s %d %s", p.name, p.age, p.gender)
}

func directWriteADTToFile(path string, players []Player) error {
	f, err := os.Create(path)
	if err != nil {
		fmt.Println("open file failed:", err)
		return err
	}
	defer func() {
		f.Sync()
		f.Close()
	}()
	for _, player := range players {
		_, err = fmt.Fprintf(f, "%s\n", player) // Player 实现了 String() 方法，格式化时会调用此方法
		if err != nil {
			return err
		}
	}
	return nil
}

func directReadFromFile(path string) error {
	f, err := os.Open(path)
	if err != nil {
		fmt.Println("open file failed:", err)
		return err
	}
	defer f.Close()
	var player Player
	for {
		// Fscanf仅支持扫描原生类型或底层类型为原生类型的数据
		_, err := fmt.Fscanf(f, "%s %d %s", &player.name, &player.age, &player.gender)
		if err == io.EOF {
			fmt.Println("read meet EOF")
			return nil
		}
		if err != nil {
			fmt.Println("read file error:", err)
			return err
		}
		fmt.Printf("%s %d %s\n", player.name, player.age, player.gender)
	}

	return nil
}

func main() {
	var players = []Player{
		{"zyl", 20, "male"},
		{"zzz", 100, "female"},
		{"yyy", 88, "male"},
	}
	err := directWriteADTToFile("2.txt", players) //ADT:抽象数据类型
	if err != nil {
		fmt.Println("write file error: ", err)
		return
	}
	err = directReadFromFile("2.txt")

}
